import json
from typing import Any
import uuid

from fastapi import APIRouter

from DataModels.database import User
from DataModels.share import (
    RespResultCode,
    RespInfo,
    StatusInfo,
    SMSConfig,
    SMSTemplateEnum,
)
from config import logger
from utils.share import timestamp
from utils.sms import send_code, random_code

send_router = APIRouter(prefix="/send")


@send_router.post("", response_model=RespInfo)
async def send(data: SMSConfig):
    """
    发送验证码，当前，发送函数会阻塞程序的一个线程；

    上线后如果出现整体阻塞， 可使用 FastAPI 的 Background Task来改善；
    但这样无法得知发送的结果，出问题也不知道可能是怎么回事。

    - BackgroundTasks 相关文档参见： https://fastapi.tiangolo.com/zh/tutorial/background-tasks/

    """

    if data.template == SMSTemplateEnum.SecretKey:
        return await send_secret_key(data)

    elif data.template == SMSTemplateEnum.Verify:
        return await send_code_for_verify(data)

    else:
        return RespInfo(
            status=StatusInfo(
                code=RespResultCode.TemplateNotExist,
                msg="短信模板不存在",
            )
        )


async def send_secret_key(cfg: SMSConfig) -> RespInfo:
    if cfg.params is None:
        return RespInfo(
            status=StatusInfo(
                code=RespResultCode.ParamsNotEnough,
                msg="参数不足",
            )
        )
    result = send_code(
        cfg.phone,
        cfg.params,
        template_id=cfg.template.value,  # type: ignore # 在这个位置，可以确定 cfg.template 不是 None
    )

    return send_ok_or_not(result, "密钥")


async def send_code_for_verify(cfg: SMSConfig) -> RespInfo:
    code = random_code()
    user = await User.find_one(User.phone == cfg.phone)
    if user:
        user.code = code
        user.verified = False
        await user.save()  # type: ignore
    else:
        user = User(
            uid=str(uuid.uuid4()),
            nick=f"User{str(uuid.uuid4())[:5]}",
            phone=cfg.phone,
            code=code,
            verified=False,
            created=timestamp(),
        )
        await user.insert()  # type: ignore

    result = send_code(
        cfg.phone,
        [code],
        template_id=cfg.template.value,  # type: ignore # 在这个位置，可以确定 cfg.template 不是 None
    )
    return send_ok_or_not(result, "验证码")


def send_ok_or_not(result: Any, what: str):
    try:
        result_json = json.loads(result)  # type: ignore
        logger.info(result_json)
        return RespInfo(
            status=StatusInfo(
                code=RespResultCode.Success,
                msg=f"{what}发送成功",
            )
        )
    except Exception as e:
        logger.error(e)
        return RespInfo(
            status=StatusInfo(
                code=RespResultCode.SendCodeErr,
                msg=f"{what}发送失败, 请稍后再试或者联系管理员",
            )
        )
